#ifndef __SUBSYSTEM_BODIES_BLOCK_BEHAVIOR_H__
#define __SUBSYSTEM_BODIES_BLOCK_BEHAVIOR_H__

#include <vector>
#include <unordered_map>
#include <mutex>

#include "Subsystem.hpp"

#include "Engine/Vector2.hpp"
#include "Engine/Vector3.hpp"

using namespace PocketSurvival::Engine;


namespace PocketSurvival
{
    struct ComponentBody;
    struct BodyRaycastResult;
    class SubsystemTimeOfDay;

    class SubsystemBodies : public Subsystem
    {
    protected:
        SubsystemTimeOfDay *m_timeOfDay;

        std::mutex m_bodiesMutex;
        // body所处的区域表
        std::unordered_map<int64_t, std::unordered_set<ComponentBody*>> m_componentBodiesByArea;
        // 记录body所出在哪个区域
        std::unordered_map<ComponentBody*, int64_t> m_bodyKeyMap;

    protected:
        void updateBody(ComponentBody *componentBody);

    public:
        void findBodiesAroundPoint(const Vector2 &point, float radius, std::vector<ComponentBody*> &result);
        void findBodiesAroundPoint(const Vector2 &point, float radius, std::unordered_set<ComponentBody*> &result);
        void findBodiesInArea(const Vector2 &corner1, const Vector2 &corner2, std::vector<ComponentBody*> &result);

        std::shared_ptr<BodyRaycastResult> raycast(const Vector3 &start, const Vector3 &end, float inflateAmount, std::function<bool(ComponentBody*, float)> func);

        virtual void update(float dt) override;
        virtual void load(const nlohmann::json& json) override;
        virtual void onEntityAdded(entt::entity entity) override;
        virtual void onEntityRemoved(entt::entity entity) override;

        virtual const std::string& getName() const override;
        virtual SubUpdateType getUpdateType() override;

    public:
        SubsystemBodies();
    };

    inline SubsystemBodies::SubsystemBodies() {}
}

#endif